package com.cea.papyrus.tabbedproperties.section;

import java.io.File;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Image;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLFactory;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.tabbedproperties.PropertyViewSection;
import com.cea.papyrus.core.ui.dialogs.PapyrusMessageDialog;

/**
 * This class handles capture of more than one icon for a stereotype. 
 * Each icon has a associated expression. (This expression has to be evaluated
 * to true to enable icon display, but this is out of the scope of this class).
 *  
 * @author Chokri Mraidha
 *
 */
public class StereotypeMultiIconSection extends PropertyViewSection {


	private Button browseButton, removeButton;
	
	private MouseListener browseButtonListener, removeButtonListener;
	
	private Table iconTable;

	private Text exprText;
	
	private String sectionLabel = "Icon:";
	
	private String expressionLabel = "Expression:";
	
	private FocusListener exprFocusListener;
	

	private final org.eclipse.swt.graphics.Image remove_img 
	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"Delete_16x16.gif");
	
	private final org.eclipse.swt.graphics.Image add_img
	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"Add_16x16.gif");

	@Override
	public void createControls(Composite parent,
			TabbedPropertySheetPage tabbedPropertySheetPage) {

		super.createControls(parent, tabbedPropertySheetPage);
		final Composite composite = getWidgetFactory().createFlatFormComposite(parent);
		FormData data;

		// iconTable 
		iconTable = getWidgetFactory().createTable(composite, SWT.BORDER | SWT.SINGLE);
        
		// buttons 
		browseButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		browseButton.setImage(add_img);
		removeButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		removeButton.setImage(remove_img);
        
        exprText = getWidgetFactory().createText(composite, "", SWT.BORDER);
        
		CLabel iconLabel = getWidgetFactory().createCLabel(composite, sectionLabel);

		CLabel exprLabel = getWidgetFactory().createCLabel(composite, expressionLabel);
		
		// iconTable layout
		data = new FormData(250, 70);
		data.left = new FormAttachment(0, 85);
		data.top  = new FormAttachment(browseButton, ITabbedPropertyConstants.VSPACE);
		iconTable.setLayoutData(data);
		
		// iconLabel layout
		data = new FormData();
		data.left  = new FormAttachment(0, 0);
		data.top   = new FormAttachment(browseButton, 0, SWT.CENTER);
		iconLabel.setLayoutData(data);

		// browseButton layout
		data = new FormData();
		data.right = new FormAttachment(removeButton, ITabbedPropertyConstants.HSPACE);
		data.top  = new FormAttachment(0, ITabbedPropertyConstants.VSPACE);
		browseButton.setLayoutData(data);

		// removeButton layout
		data = new FormData();
		data.right = new FormAttachment(iconTable, 0, SWT.RIGHT);
		data.top  = new FormAttachment(browseButton, 0, SWT.CENTER);
		removeButton.setLayoutData(data);
		
		// exprLabel layout
		data = new FormData();
		data.left = new FormAttachment(iconTable, ITabbedPropertyConstants.HSPACE*10);
		data.top = new FormAttachment(0, ITabbedPropertyConstants.VSPACE);
		exprLabel.setLayoutData(data);
		
		// exprText layout
		data = new FormData(350, 80);
		data.left = new FormAttachment(iconTable, ITabbedPropertyConstants.HSPACE*10);
		data.top = new FormAttachment(browseButton, ITabbedPropertyConstants.VSPACE);
		exprText.setLayoutData(data);

		exprText.addFocusListener(exprFocusListener = new FocusListener() {
    		public void focusGained(FocusEvent e){
    		}
    		public void focusLost(FocusEvent e){
    			if((iconTable.getSelection() != null) && (iconTable.getSelection().length > 0)) {
    				TableItem[] items = iconTable.getSelection();
    				if(getUml2Stereotype()!=null) {
    					Stereotype umlStereo = getUml2Stereotype();
    					com.cea.papyrus.umlutils.Stereotype ceaStereo = new com.cea.papyrus.umlutils.Stereotype(umlStereo);
    					int selectedIndex = iconTable.getSelectionIndex();
    					String oldExpression = null;
    					if(ceaStereo.hasIcon()){
    						if(selectedIndex==0) {
    							oldExpression = getExpression(umlStereo.getIcons().get(0)); 
    							setExpression(umlStereo.getIcons().get(0), exprText.getText().trim());
    						}
    						else {
    							oldExpression = getExpression(umlStereo.getIcons().get(selectedIndex+1));
    							setExpression(umlStereo.getIcons().get(selectedIndex+1), exprText.getText().trim());
    						}
    					}
    					
    					else {
    						if(selectedIndex==0) {
    							oldExpression = getExpression(umlStereo.getIcons().get(2));
    							setExpression(umlStereo.getIcons().get(2), exprText.getText().trim());
    						}
    						else {
    							oldExpression = getExpression(umlStereo.getIcons().get(selectedIndex+2));
    							setExpression(umlStereo.getIcons().get(selectedIndex+2), exprText.getText().trim());
    						}
    					}
    					
    					/* if the expression changed, then forceToSave */
    					if(!oldExpression.equals(exprText.getText().trim()))
    						forceToSave();
    				}
    			}
    			refresh();
    		}
        });

		
		
		
		// Add icon listener
		browseButton.addMouseListener(browseButtonListener = new MouseListener() {

			public void mouseDoubleClick(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
			}

			public void mouseUp(MouseEvent e) {
				FileDialog fd = new FileDialog(composite.getShell());
				String extensions[] = {"*.jpg;*.bmp;*.ico;*.gif;*.png;*.wmf;*.emf"};
				fd.setFilterExtensions(extensions);
				String iconSelected = fd.open();

				// No image selected
				if (iconSelected == null) {
					return;
				}

				if(getElement() instanceof Stereotype) {

					File imgFile = new File(iconSelected);
					com.cea.papyrus.umlutils.Stereotype stereotype = new com.cea.papyrus.umlutils.Stereotype((Stereotype) getElement());

					try{
						/* treat the case of the first icon apart because its index is 0
						 * and index of the following icon is 2 
						 */
						int nbr = stereotype.getNbrOfIcons();
						if(!stereotype.hasIcon())
							stereotype.setIcon(imgFile);
						else
							stereotype.setIcon(imgFile, nbr);
						
						refresh();
					} catch (Exception ex) {
						PapyrusMessageDialog.display("Could not import image.", null);
						
					}
				}
			}
		});

		removeButton.addMouseListener(removeButtonListener = new MouseListener() {

			public void mouseDoubleClick(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
			}

			public void mouseUp(MouseEvent e) {
				// Default img
				if(getElement() instanceof Stereotype) {

					com.cea.papyrus.umlutils.Stereotype stereotype = new com.cea.papyrus.umlutils.Stereotype((Stereotype) getElement());

					try{
						int selectedIndex = iconTable.getSelectionIndex();
						int count = iconTable.getItemCount();
						if(count == 1){
							stereotype.getUml2Stereotype().getIcons().remove(iconTable.getSelection()[0].getData());
							stereotype.setIcon(null);
						}
						
						/* we leave this one here to handle the case of deletion of the first icon
						 * before deletion of the following icons 
						 */
						else if(selectedIndex==0){
							stereotype.setIcon(null);
						}
						
						else {
							stereotype.getUml2Stereotype().getIcons().remove(iconTable.getSelection()[0].getData());
						}
						refresh();
					} catch (Exception ex) {
						PapyrusMessageDialog.display("Could not remove image.", null);
					}
				}
			}
		});
	}

	@Override
	public void refresh() {
		/* intitialization of buttons enabling */
		if(!browseButton.isDisposed()){
			if(!(getElement() instanceof Stereotype)) {
				return;
			}
			com.cea.papyrus.umlutils.Stereotype stereotype = new com.cea.papyrus.umlutils.Stereotype((Stereotype) getElement());
			
			// Initialize icons list with null if necessary
			if(stereotype.getUml2Stereotype().getIcons().size() < 1) {
				Image DEFAULT_ICON = UMLFactory.eINSTANCE.createImage();
				stereotype.getUml2Stereotype().getIcons().add(0, DEFAULT_ICON);
			}
			
			// Default img
			if(stereotype.getUml2Stereotype().getIcons().size() < 2) {
				Image DEFAULT_IMAGE = UMLFactory.eINSTANCE.createImage();
				stereotype.getUml2Stereotype().getIcons().add(1, DEFAULT_IMAGE);
			}   	
			

			/* display all icons in iconTable */
			iconTable.removeAll();
			int nbr = stereotype.getNbrOfIcons();
			
			
			if(nbr>0){
				/* treat the first icon which index is 0 */
				TableItem iconItem = new TableItem(iconTable, SWT.NONE);
				iconItem.setData(stereotype.getUml2Stereotype().getIcons().get(0));
				iconItem.setImage(stereotype.getIcon(0));
				String location = stereotype.getUml2Stereotype().getIcons().get(0).getLocation();
				if(location != null)
					iconItem.setText(location);
				else
					iconItem.setText("--no expression--");
				iconTable.addMouseListener(new DblClickListener());
			}	

			int size = stereotype.getUml2Stereotype().getIcons().size();
			
			/* other icons are placed after the shape which index is 1 */
			if(size>2){
				for(int i=2; i<size; i++){
					TableItem iconItem2 = new TableItem(iconTable, SWT.NONE);
					iconItem2.setData(stereotype.getUml2Stereotype().getIcons().get(i));
					iconItem2.setImage(stereotype.getIcon(i));
					String location = stereotype.getUml2Stereotype().getIcons().get(i).getLocation();
					if(location != null)
						iconItem2.setText(location);
					else
						iconItem2.setText("--no expression--");
				}
			}

			// Get Icon
			//org.eclipse.swt.graphics.Image icon = stereotype.getIcon();
			// Refresh text 
			//if(icon != null) {
				// Resize icon to 32x32
//				org.eclipse.swt.graphics.Image resizedIcon
//				= new org.eclipse.swt.graphics.Image(
//						icon.getDevice()
//						, icon.getImageData().scaledTo(16, 16));
//				browseButton.setImage(resizedIcon);
				removeButton.setEnabled(true);

			/*} else {
				browseButton.setImage(add_img);
				removeButton.setEnabled(false);
			}  */ 	
				
				exprText.setText("");
		}

	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.properties.tabbed.PropertyViewSection#dispose()
	 */
	public void dispose(){
		super.dispose();
		if(browseButton!=null && !browseButton.isDisposed())
			browseButton.removeMouseListener(browseButtonListener);
		if(removeButton!=null && !removeButton.isDisposed())
			removeButton.removeMouseListener(removeButtonListener);
	}
	
	/**
	 * Returns selected uml2 stereotype
	 * @return
	 */
	public Stereotype getUml2Stereotype() {
		if(getElement() instanceof Stereotype)
			return (Stereotype)getElement();
		else
			return null;
	}
	
	/**
	 * Associates an expression to an image
	 * @param image
	 * @param expression
	 */
	private void setExpression(Image image, String expression){
		image.setLocation(expression);
	}
	
	/**
	 * Returns the expression associated to the image
	 * @param image
	 * @return the expression associated to the image
	 */
	private String getExpression(Image image) {
		return image.getLocation();
	}
	
	
	private class DblClickListener implements MouseListener {
		

		public void mouseDoubleClick(MouseEvent e) {
		}

		public void mouseDown(MouseEvent e) {
		}

		public void mouseUp(MouseEvent e) {
			exprText.setText("");
			exprText.setText(iconTable.getSelection()[0].getText());
		}
	}
}


